package com.blue.waffle.iwc.domains.helpers;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import com.blue.waffle.iwc.domains.Profile;
import com.blue.waffle.iwc.utils.LruCache;

public class ProfileHelper implements DataHelper<Profile> {

	private Connection connection;
	private static final String TABLE_NAME="profile";
	private PreparedStatement selectStatement;
	private PreparedStatement updateStatement;
	private PreparedStatement insertStatement;
	private PreparedStatement deleteStatement;
	private static final String SELECT_ALL_SQL="SELECT * FROM "+TABLE_NAME;
	private static LruCache<Integer, Profile> objectCache;
	private static final String INSERT_SQL="INSERT INTO "+TABLE_NAME+" (name,level_random_seed,last_played_level_index, attempts) VALUES (?,?,?,?)";
	private static final String UPDATE_SQL="UPDATE "+TABLE_NAME+" SET name=?, level_random_seed=?, last_played_level_index=?, current_difficulty=? , attempts=? WHERE id=?";
	private static final String DELETE_SQL="DELETE FROM "+TABLE_NAME+" WHERE id=?";
	private static final String SELECT_EXIST_SQL = "SELECT 1 FROM "+TABLE_NAME+" WHERE id=?";
	
	public ProfileHelper(Connection connection) {
		this.connection=connection;
		if (objectCache==null) {
			objectCache=new LruCache<Integer, Profile>(10);
		}
	}

	@Override
	public boolean isClosed() throws SQLException {
		if (connection!=null) {
			return connection.isClosed();
		}
		return false;
	}
	
	@Override
	public void close() throws SQLException{
		if (connection!=null ) {
			if (!connection.isClosed()) {
				connection.close();
			}
			connection=null;
		}
	}
	@Override
	public void setConnection(Connection connection) {
		this.connection = connection;
	}

	@Override
	public List<Profile> selectAll() throws SQLException {
		Statement statement=connection.createStatement();
		ResultSet resultSet=statement.executeQuery(SELECT_ALL_SQL);
		List<Profile> list=new ArrayList<Profile>();
		while (resultSet.next()) {
			list.add(getObject(resultSet));
			System.out.println(objectCache.getHits());
		}
		resultSet.close();
		return list;
	}


	@Override
	public List<Profile> select(String sql, Object[] para) throws SQLException {
		// TODO Auto-generated method stub
		return null;
	}


	@Override
	public void insert(Profile model) throws SQLException {
		insertStatement=connection.prepareStatement(INSERT_SQL);
		insertStatement.setString(1, model.getName());
		insertStatement.setLong(2, model.getLevelRandomSeed());
		insertStatement.setLong(3, model.getLastPlayedLevel());
		insertStatement.setInt(4, model.getAttempts());
		insertStatement.executeUpdate();
		Statement statement=connection.createStatement();
		ResultSet keyGenerated=statement.executeQuery("SELECT last_insert_rowid()");
		if (keyGenerated.next()) {
			int id=keyGenerated.getInt(1);
			System.out.println(id);
			model.setId(id);
			objectCache.put(id, model);
		}
		keyGenerated.close();
		insertStatement.close();
	}


	@Override
	public void update(Profile model) throws SQLException {
		updateStatement=connection.prepareStatement(UPDATE_SQL);
		updateStatement.setString(1, model.getName());
		updateStatement.setLong(2, model.getLevelRandomSeed());
		updateStatement.setLong(3, model.getLastPlayedLevel());
		updateStatement.setLong(4, model.getCurrentDifficulty().getId());
		updateStatement.setInt(5, model.getAttempts());
		updateStatement.setInt(6, model.getId());
		updateStatement.executeUpdate();
		objectCache.put(model.getId(), model);
		updateStatement.close();
	}


	@Override
	public void delete(Profile model) throws SQLException {
		deleteStatement=connection.prepareStatement(DELETE_SQL);
		deleteStatement.setInt(1, model.getId());
		deleteStatement.executeUpdate();
		objectCache.remove(model.getId());
		deleteStatement.close();
	}
	
	public void clearObjectCache() {
		objectCache.clear();
	}


	@Override
	public int count(String sql) throws SQLException {
		// TODO Auto-generated method stub
		return 0;
	}


	@Override
	public int count() throws SQLException {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public Profile getObject(ResultSet resultSet) throws SQLException {
		int id=resultSet.getInt(Profile.ID);
		Profile profile=objectCache.get(id);
		if (profile==null) {
			profile=new Profile();
			profile.setId(id);
			objectCache.put(id, profile);
		}
		profile.setName(resultSet.getString(Profile.NAME));
		profile.setLevelRandomSeed(resultSet.getLong(Profile.LEVEL_RANDOM_SEED));
		profile.setLastPlayedLevel(resultSet.getLong(Profile.LAST_PLAYED_LEVEL_INDEX));
		profile.setCurrentDifficulty(resultSet.getInt(Profile.CURRENT_DIFFICULTY));
		profile.setAttempts(resultSet.getInt(Profile.ATTEMPT));
		return profile;
	}

	public void save(Profile model) throws SQLException {
		selectStatement=connection.prepareStatement(SELECT_EXIST_SQL);
		selectStatement.setInt(1,model.getId());
		ResultSet isExist=selectStatement.executeQuery();
		boolean exist=false;
		if (isExist.next()) {
			exist=isExist.getBoolean(1);
		}
		isExist.close();
		selectStatement.close();
		if (exist) {
			update(model);
		}else {
			insert(model);
		}
	}
	
	/*
	@Override
	public void insertBatch(List<Profile> models) throws SQLException {
		insertStatement=connection.prepareStatement(INSERT_SQL);
		connection.setAutoCommit(false);
		for (Profile profile : models) {
			insertStatement.setString(1, profile.getName());
			insertStatement.addBatch();
		}
		int[] rows=insertStatement.executeBatch();
		connection.commit();
		connection.setAutoCommit(true);
	}

	@Override
	public void updateBatch(List<Profile> models) throws SQLException {
		updateStatement=connection.prepareStatement(UPDATE_SQL);
		connection.setAutoCommit(false);
		for (Profile profile : models) {
			updateStatement.setString(1, profile.getName());
			updateStatement.setInt(2, profile.getId());
			updateStatement.addBatch();
		}
		int[] rows=updateStatement.executeBatch();
		connection.commit();
		connection.setAutoCommit(true);
	}*/

}
